package com.px.baolaiapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.px.common.api.CommonPage;
import com.px.common.api.CommonResult;
import com.px.common.constant.Constant;
import com.px.common.execption.Asserts;
import com.px.mbg.model.*;
import com.px.mbg.mapper.OutsourceReturnOrderMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.baolaiapi.dto.OutsourceReturnOrderDto;
import com.px.baolaiapi.enums.ReceiptsTypeEnum;
import com.px.baolaiapi.page.OutsourceReturnOrderPage;
import com.px.baolaiapi.service.*;
import com.px.baolaiapi.util.JwtTokenUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * <p>
 * 委外退货单 服务实现类
 * </p>
 *
 * @author 品讯科技
 * @since 2022-05-19
 */
@Service
public class OutsourceReturnOrderServiceImpl extends ServiceImpl<OutsourceReturnOrderMapper, OutsourceReturnOrder> implements IOutsourceReturnOrderService {


    @Autowired
    private IToDoListService toDoListService;
    @Autowired
    private IOutsourceReturnDetailService outsourceReturnDetailService;
    @Autowired
    private IUsersService usersService;
    @Autowired
    private ISequenceNumberService sequenceNumberService;
    @Autowired
    private IDocumentTypeService documentTypeService;
    @Autowired
    private ICommonBillService commonBillService;
    @Autowired
    private IBomService bomService;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    private IInOutOfBillService inOutOfBillService;
    @Autowired
    private IStorageService storageService;

    @Autowired
    private IUnitCnvRateService unitCnvRateService;
    @Autowired
    private IUnitService unitService;


    /**
     * 执行接口的逻辑
     *
     * @param datas mes交互数据
     * @return {@link CommonResult}
     */
        public CommonResult operationInterface(Object datas) {

        JSONObject paramJson = JSONUtil.parseObj(datas);
        //组织ID
        Long organizationId = paramJson.getLong("organizationId");
        //单据类型
        String bnoType = paramJson.getStr("receiptsType");
        //单据编号
        String bnoNo = paramJson.getStr("bnoNo");
        //委外加工商编码
        String supplierCode = paramJson.getStr("supplierCode");
        //委外加工商名称
        String supplierName = paramJson.getStr("supplierName");
        //制单日期
        String createDate = paramJson.getStr("date");
//        //委外加工单号
//        String outSourceNo = paramJson.getStr("outSourceNo");
        //制单人
//        String createUserCode = paramJson.getStr("sendPeople");
        //退货部门
        String returnDep = paramJson.getStr("return_dep");

        OutsourceReturnOrderDto outsourceReturnOrderDto = new OutsourceReturnOrderDto();
        outsourceReturnOrderDto.setOrganizationId(organizationId);
        outsourceReturnOrderDto.setBnoType(bnoType);
        outsourceReturnOrderDto.setBnoNo(bnoNo);
        outsourceReturnOrderDto.setSupplierCode(supplierCode);
        outsourceReturnOrderDto.setSupplierName(supplierName);
//        outsourceReturnOrderDto.setUserAccount(createUserCode);
//        sendReturnMaterialListDto.setCreateDate(createDate);
//        outsourceReceiveOrderDto.setOutSourceNo(outSourceNo);
//        Users users = usersService.queryUserByAccount(createUserCode);
//        if (ObjectUtil.isNotEmpty(users)) {
//            outsourceReturnOrderDto.setUserName(users.getUsername());
//        }
        outsourceReturnOrderDto.setReturnDep(returnDep);


        JSONArray items = paramJson.getJSONArray("items");
        if (items.size()>0) {
            List<OutsourceReturnDetail> outsourceReturnDetails = new ArrayList<>();
            for (int i = 0; i < items.size(); i++) {
                OutsourceReturnDetail outsourceReturnDetail = new OutsourceReturnDetail();

                JSONObject jsonObject = items.getJSONObject(i);
                //行号
                String lineNo = jsonObject.getStr("lineNo");
                outsourceReturnDetail.setLineNo(lineNo);
                //来源类别
                String sourceCategory = jsonObject.getStr("sourceCategory");
                outsourceReturnDetail.setSourceCategory(sourceCategory);
                //委外加工单号
                String outSourceNoItem = jsonObject.getStr("sourceNumber");
                outsourceReturnDetail.setOutSourceNo(outSourceNoItem);
                //料号
                String materialCode = jsonObject.getStr("materialCode");
                outsourceReturnDetail.setMaterialCode(materialCode);
                //品名
                String materialName = jsonObject.getStr("materialName");
                outsourceReturnDetail.setMaterialName(materialName);
                //可退数量
                String returnableNum = jsonObject.getStr("returnableNum");
                outsourceReturnDetail.setPcsNum(new BigDecimal(returnableNum));
                //发库存单位
                String pcsUnit = jsonObject.getStr("pcsUnit");
                outsourceReturnDetail.setPcsUnit(pcsUnit);
                //计价单位
                String measureUnit = jsonObject.getStr("measureUnit");
                outsourceReturnDetail.setMeasureUnit(measureUnit);
                outsourceReturnDetails.add(outsourceReturnDetail);

            }
            outsourceReturnOrderDto.setOutsourceReturnDetailList(outsourceReturnDetails);
        }
        //调用add方法
        int status = addOutsourceReturnOrder(outsourceReturnOrderDto);
        if (status > 0) {
            return CommonResult.success(status);
        }
        return CommonResult.failed();
    }

    @Override
    public int addOutsourceReturnOrder(OutsourceReturnOrderDto outsourceReturnOrderDto) {
        OutsourceReturnOrder bill = new OutsourceReturnOrder();
        BeanUtils.copyProperties(outsourceReturnOrderDto,bill);

        ReceiptsTypeEnum receiptsTypeEnum = ReceiptsTypeEnum.WWTHD;
        bill.setReceiptsType(receiptsTypeEnum.getValue());

        String bnoType = bill.getBnoType();
        Preconditions.checkArgument(StringUtils.isNotBlank(bnoType), "单据类型必选");
        //单据类型同步后,获取位置变更
        DocumentType documentType = documentTypeService.getById(bnoType);
        if (ObjectUtil.isNull(documentType)) {
            Asserts.fail("未匹配到委外退货单据类型");
        }

        //String bnoNo = sequenceNumberService.createSequenceNumberRod(bnoType, "yyyy", 4, StrUtil.DASHED);
        String bnoNo = sequenceNumberService.createSequenceNumberRod("BLWTH", "yyMM", 4, "");
        bill.setBnoNo(bnoNo);

        Users user = jwtTokenUtils.getUser();
        bill.setUserName(user.getUsername());
        bill.setUserAccount(user.getAccount());

        //不需要批号,从委外收货中获取
        //String batchNo = commonBillService.genBatchNo(bnoType);

        bill.setFinishFlag(Constant.ORDER_FINISH_FLAG.UN_FINISH);

        if(this.save(bill)){
            List<OutsourceReturnDetail> outsourceReturnDetailList = outsourceReturnOrderDto.getOutsourceReturnDetailList();
            outsourceReturnDetailList.forEach(e -> {
                e.setOutsourceReturnId(bill.getId());
            });
            if(CollectionUtil.isNotEmpty(outsourceReturnDetailList)){
                outsourceReturnDetailService.saveBatch(outsourceReturnDetailList);
            }


            // 添加待办任务记录
            toDoListService.addToDoList(bill.getId(), bill.getBnoNo(), receiptsTypeEnum, bill.getBnoType(), bill.getSupplierName());


            return 1;
        }
        return 0;
    }

    @Override
    public CommonPage queryOutsourceReturnOrderPage(OutsourceReturnOrderPage page) {
        LambdaQueryWrapper<OutsourceReturnOrder> queryWrapper = Wrappers.lambdaQuery(OutsourceReturnOrder.class);
        String bnoNo = page.getBnoNo();
        if (StringUtils.isNotEmpty(bnoNo)) {
            queryWrapper.like(OutsourceReturnOrder::getBnoNo, bnoNo);
        }
        String bnoType = page.getBnoType();
        if(StringUtils.isNotEmpty(bnoType)){
            queryWrapper.like(OutsourceReturnOrder::getBnoType, bnoType);
        }
        String startDate = page.getStartDate();
        if (StringUtils.isNotEmpty(startDate)) {
            queryWrapper.ge(OutsourceReturnOrder::getCreateDate, startDate);
        }
        String endDate = page.getEndDate();
        if (StringUtils.isNotEmpty(endDate)) {
            queryWrapper.le(OutsourceReturnOrder::getCreateDate, endDate);
        }
        queryWrapper.eq(page.getFinishFlag() != null && page.getFinishFlag() >= 0, OutsourceReturnOrder::getFinishFlag, page.getFinishFlag());
        queryWrapper.eq(OutsourceReturnOrder::getIsDelFlag, Constant.IS_ENABLED.ENABLE);
        queryWrapper.orderByDesc(OutsourceReturnOrder::getUpdatedTime);

        CommonPage commonPage = CommonPage.restPage(this.page(new Page<>(page.getPageNum(), page.getPageRow()), queryWrapper));
        List<OutsourceReturnOrder> list = commonPage.getList();
        List<JSONObject> jsonObjects = new ArrayList<>();
        for (OutsourceReturnOrder outsourceReturnOrder : list) {
            JSONObject jsonObject = billToJSONObject(outsourceReturnOrder);
            jsonObjects.add(jsonObject);
        }
        commonPage.setList(jsonObjects);
        return commonPage;
    }

    @Override
    public JSONObject queryOutsourceReturnOrderById(long id) {
        OutsourceReturnOrder outsourceReturnOrder = this.getById(id);
        if (ObjectUtil.isNotEmpty(outsourceReturnOrder)) {
            JSONObject jsonObject = billToJSONObject(outsourceReturnOrder);

            List<JSONObject> dtoList = new ArrayList();
            List<OutsourceReturnDetail> list = outsourceReturnDetailService.list(new QueryWrapper<OutsourceReturnDetail>().lambda().eq(OutsourceReturnDetail::getOutsourceReturnId, id).eq(OutsourceReturnDetail::getIsDelFlag, Constant.IS_ENABLED.ENABLE));
            if(CollectionUtils.isNotEmpty(list)){
                for (OutsourceReturnDetail item : list) {

                    // 可退重量
                    String pcsWeight = "";
                    // 实退重量
                    String rWeight = "";
                    // 单位转换率转换完重量的单位
                    String weightUnit = "";


                    JSONObject dto = JSONUtil.parseObj(item);
                    // 实际数量
                    BigDecimal rNum = inOutOfBillService.getSumRealNumByBnoNoAndDetailId(outsourceReturnOrder.getBnoNo(), item.getId());
                    dto.set("rNum", rNum);
                    // 单位
                    Map<String, Object> unitCN = bomService.getUnitCN(item.getWidthUnit(), item.getLengthUnit(), item.getThicknessUnit(), item.getWeightUnit(), item.getPcsUnit());
                    dto.putAll(unitCN);

                    // 组织单位转换率数据
                    UnitCnvRate unitCnvRate = unitCnvRateService.queryUnitCnvRateByBomCodeAndUnit(item.getMaterialCode(),item.getPcsUnit());
                    if (ObjectUtil.isNotNull(unitCnvRate)) {
                        pcsWeight = String.valueOf(unitCnvRate.getCnvRate().multiply(item.getPcsNum()).setScale(2, BigDecimal.ROUND_UP));
                        rWeight = String.valueOf(unitCnvRate.getCnvRate().multiply(rNum).setScale(2, BigDecimal.ROUND_UP));
                        Unit unit = unitService.queryUnitByCode("",unitCnvRate.getTgtUnit());
                        if (ObjectUtil.isNotNull(unit)) {
                            weightUnit = unit.getUnitName();
                        }
                    }

                    dto.set("rWeight", rWeight);
                    dto.set("pcsWeight", pcsWeight);
                    dto.set("weightUnit",weightUnit);



                    dtoList.add(dto);
                }
            }
            jsonObject.set("outsourceReturnDetailList", dtoList);

            return jsonObject;
        }

        return new JSONObject();
    }

    private JSONObject billToJSONObject(OutsourceReturnOrder outsourceReturnOrder){
        JSONObject dto = JSONUtil.parseObj(outsourceReturnOrder);
        //转换单据类型(U9)
        //单据类型同步后,获取位置变更
        DocumentType documentType = documentTypeService.getOne(new LambdaQueryWrapper<DocumentType>().eq(DocumentType::getOrganizationId,jwtTokenUtils.getOrganizationId())
                .eq(DocumentType::getName,Constant.BILL_CLASSIFICATION_U9.RECEIPTS_TYPE.WWTHD));
        if (ObjectUtil.isNotNull(documentType)) {
            dto.set("bnoTypeName", documentType.getName());
        }

        // 库房编码转名称
        String storeAddress = outsourceReturnOrder.getStoreAddress();
        Storage storage = storageService.queryStorageByCode(storeAddress);
        dto.set("storeAddressName", Optional.ofNullable(storage).map(Storage::getName).orElse(null));
        return dto;
    }

    
    public Object generateU9Data(String bnoNo, List<InOutOfBill> inOutOfBillList) {
        JSONObject jsonObject = new JSONObject();
        OutsourceReturnOrder outsourceReturnOrder = this.getOne(new QueryWrapper<OutsourceReturnOrder>().lambda().eq(OutsourceReturnOrder::getBnoNo,bnoNo).eq(OutsourceReturnOrder::getIsDelFlag,Constant.IS_ENABLED.ENABLE));
        jsonObject.set("organizationId",outsourceReturnOrder.getOrganizationId());
        jsonObject.set("organizationCode",outsourceReturnOrder.getOrganizationCode());
        jsonObject.set("organizationName",outsourceReturnOrder.getOrganizationName());
        jsonObject.set("bnoType",outsourceReturnOrder.getBnoType());
        jsonObject.set("bnoNo",outsourceReturnOrder.getBnoNo());
        jsonObject.set("supplierCode",outsourceReturnOrder.getSupplierCode());
        jsonObject.set("supplierName",outsourceReturnOrder.getSupplierName());
        jsonObject.set("createDate",outsourceReturnOrder.getCreateDate());
        jsonObject.set("storeAddress",outsourceReturnOrder.getStoreAddress());
        jsonObject.set("storeKeeperCode",inOutOfBillList.get(0).getUserAccount());
        jsonObject.set("returnDep",outsourceReturnOrder.getReturnDep());
        jsonObject.set("outSourceNo",outsourceReturnOrder.getOutSourceNo());
        jsonObject.set("createUserCode",outsourceReturnOrder.getUserAccount());
        jsonObject.set("createUserName",outsourceReturnOrder.getUserName());
        jsonObject.set("configDate",inOutOfBillList.get(0).getOperateTime());
        JSONArray jsonArray = new JSONArray();
        for (InOutOfBill inOutOfBill : inOutOfBillList) {
            OutsourceReturnDetail detail = outsourceReturnDetailService.getById(inOutOfBill.getBillDetailId());
            JSONObject jsonDetail = new JSONObject();
            jsonDetail.set("lineNo",detail.getLineNo());
            jsonDetail.set("outSourceNo",detail.getOutSourceNo());
            jsonDetail.set("materialCode",detail.getMaterialCode());
            jsonDetail.set("materialName",detail.getMaterialName());
            jsonDetail.set("specification",detail.getSpecification());
            jsonDetail.set("batchNo",detail.getBatchNo());
            jsonDetail.set("storeAddress",inOutOfBill.getStgeCode());
            jsonDetail.set("storeBinCode",inOutOfBill.getStgeLocCode());
            jsonDetail.set("backNum",inOutOfBill.getQty());
            jsonDetail.set("pcsUnit",inOutOfBill.getUnit());
            jsonDetail.set("returnableNum",detail.getPcsNum());
            jsonDetail.set("remark",detail.getRemark());
            jsonDetail.set("longt",inOutOfBill.getLongt());
            jsonDetail.set("lengthUnit",inOutOfBill.getLengthUnit());
            jsonDetail.set("width",inOutOfBill.getWidth());
            jsonDetail.set("widthUnit",inOutOfBill.getWidthUnit());
            jsonDetail.set("thickness",inOutOfBill.getThickness());
            jsonDetail.set("thicknessUnit",inOutOfBill.getThicknessUnit());
            jsonArray.add(jsonDetail);
        }
        jsonObject.set("items",jsonArray);

        return jsonObject;
    }
}
